package example.day03;

/**
 * 类型转换示例代码
 *
 * 类型自动转换的原则：
 * 1. 小范围赋值给大范围的类型，没有任何问题，自动转换
 * 2. 大范围的值，赋值给小范围的类型，如果这个值是个常量，而且在目标类型的范围之内，自动转换
 * 3. 大范围的值，赋值给小范围的类型，如果这个值是个变量，则不会自动转换（因为无法确定这个值是否会超出目标类型的范围）
 * 4. 大范围的值（超出目标类型范围的常量，或者是变量），如果非要赋值给小范围的类型，可以认为强制转换
 *
 */
public class _01_类型转换Demo {
    public static void main(String[] args) {

        /**
         * 小范围类型，赋给大范围类型，自动转
         */
        int a = 100;
        long b = a;

        /**
         * 5本身是个int，但是赋给了一个byte变量
         * 类型不一致，但是编译依然通过了
         * 原因：编译器有一个隐式类型转换的功能
         * 它帮你把int值转成了byte类型
         */
        byte b1 = 5;

        /**
         * 错误语句：
         * 原因是，编译器想帮你转，但是发现129超出了byte类型的最大范围
         * 无法转
         */
        // byte b2  = 129;

        /**
         * 上面 b1 = 5 编译通过
         * 这里 b1 = t1 编译不通过,为何？
         * 因为，5本身是个死的（常量），编译器在翻译这个语句的时候，看见的就是5，
         * 它能确定5在byte类型的范围之内，所以帮你自动隐式转换类型；
         *
         * 而 t1是个变量，变量只有在运行时才能确定值
         * 而且，t1可能在代码中有各种复杂的逻辑对其进行赋值
         * 而t1本身是个int，编译器顶多能确定 t1在int的范围之内,
         * 但很有可能会超出byte的范围，所以没法给你自动转换类型
         *
         */
        int t1 = 5;
        // b1 = t1;   报错


        short st = 1000;
        // st = t1;  // 报错，理由同上


        /**
         * 强制转换（将大范围值，赋给小范围，使用强转语法）
         * 但是，如果值真的超过了目标变量的范围，强制转换会产生数据损失
         */
        b1 = (byte)128;   // 超范围的整数强转成byte，产生了损失
        System.out.println(b1);

        b1 = (byte)t1;  // 实际没有超出byte范围的整数，强转后没有发生实际损失
        System.out.println(b1);


        // int t2 = 18.8; //  double,永远不会自动转成int，要转只能强转
        int t2 = (int)18.8;  // 产生数据损失


        /**
         * 一个特别钻牛角尖的例子
         */
        int y = 10;
        short x = 32767;

        // x = x+1; // 报错，因为表达式中有一个1（整数），整个表达式都要提升到int这个级别来运算，产生的结果也是个int
        x = (short)(x+100);

        /**
         * 下面这句话不报错
         * 是因为，java的编译器中，把 x += 10 翻译成了  x = (short)(x+10)
         */
        x += 100; // x = x+1
        System.out.println(x);



        // 报错，强转不强转，都无法通过
        // 因为true是boolean值，u是int类型，两种类型不存在大小等级范围关系
        // int u = (int)true;

        // 而下面这个又能通过
        // 因为char本质上也可以看成一个数，它就是字符对应的码表种的码点（码位），而码点就是一个数
        char c = 'a';
        int u = c;
        System.out.println(u);  // 打印出来是？ 97

        char o = 97;
        int r = 97;
        o = (char) r;
        System.out.println(o);   // 打印出来是  a


    }
}
